package com.atom.compiler.apt

import com.atom.compiler.apt.common.KotlinAnnotation
import com.atom.compiler.apt.common.KotlinInterfaceClass0
import com.atom.compiler.apt.common.KotlinInterfaceClass1
import com.atom.compiler.apt.ext.createFile
import com.atom.module.annotation.aap.AapAutoClass
import com.atom.module.annotation.aap.AapImplEntry
import com.squareup.kotlinpoet.*
import org.junit.Test
import java.io.IOException
import java.text.SimpleDateFormat
import java.util.*

//https://square.github.io/kotlinpoet/
class TestKotlinpoet {

    val PACKET : String = "result.test.apt"

    val projectPath: String = "D:\\app_git_android\\demo_asm\\test-plugin-compiler\\"

    val savePath = lazy { projectPath + "compiler-apt\\src\\test\\kotlin" }


    private fun createFile(
        packet: String,
        name: String,
        block: (FileSpec.Builder) -> Unit
    ) {
        val builder = FileSpec.builder(packet, name)
        block.invoke(builder)
        val build = builder.build()
        try {
            build.writeTo(savePath.value.createFile())
        } catch (e: IOException) {
            e.printStackTrace()
        }
    }


    @Test
    fun `测试一个基本的创建一个kt文件`() {
        val builder = FileSpec.builder(PACKET, "aap")
        val build = builder.build()
        try {
            build.writeTo(savePath.value.createFile())
        } catch (e: IOException) {
            e.printStackTrace()
        }
    }

    @Test
    fun `测试抽象的createFile方法`() {
        createFile(PACKET, "testKotlin") { // 报名和文件名称
            val pageConfigClassName = ClassName(it.packageName, "aap") // 包名和 className
            val dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ")
            // 创建一个class组装器
            val build = TypeSpec.classBuilder(ClassName(it.packageName, "aap"))
                .superclass(ClassName.bestGuess(AapImplEntry::class.qualifiedName!!)) // 设置继承
                .primaryConstructor( // 设置默认构造方法,及其参数
                    FunSpec.constructorBuilder()
                        .addParameter("name", String::class)
                        .build()
                )
                .addProperty( // 设置成员
                    PropertySpec.builder("name", String::class)
                        .initializer("name")
                        .build()
                )
                .addFunction( // 添加普通方法和方法体
                    FunSpec.builder("greet")
                        .addStatement("println(%P)", "Hello, \$name")
                        .build()
                )
                .addKdoc( // 添加注释文档
                    CodeBlock.builder()
                        .add("<p>This is a class automatically generated by API annotation processor.</p>")
                        .add("\n")
                        .add("@date ").add(dateFormat.format(Date()))
                        .add("\n")
                        .build()
                )
                .addAnnotation( // 添加注解 添加到了class 类
                    AnnotationSpec.builder(AapAutoClass::class.java)
                        .addMember("value = [%S]", dateFormat.format(Date()))
                        .addMember("data = %S", dateFormat.format(Date()))
                        .build()
                )
                .addAnnotation(// 添加注解 添加到了class 类
                    AnnotationSpec.builder(SuppressWarnings::class.java)
                        .addMember("value = [%S]", "all")
                        .build()
                )
                .build()
            it.addType(build)
            it.addFunction( // 添加一个方法
                FunSpec.builder("main")
                    .addParameter("args", String::class, KModifier.VARARG)
                    .addStatement("%T(args[0]).greet()", pageConfigClassName)
                    .build()
            )
        }
    }

    @Test
    fun `测试继承接口,分别继承和实现java和kotlin的接口类型`() {
        createFile(PACKET, "testJavaAndKotlinInterface") {
            val typeSuper = TypeSpec.classBuilder(
                ClassName(it.packageName, it.name)
            )
            typeSuper.superclass(ClassName.bestGuess(AapImplEntry::class.qualifiedName!!))
            //typeSuper.superclass(AapImplEntry::class)
            //typeSuper.superclass(ClassName("com.atom.module.annotation.aap", "AapImplEntry"))

            typeSuper.addSuperinterface(ClassName.bestGuess(KotlinInterfaceClass0::class.qualifiedName!!))
            typeSuper.addSuperinterface(KotlinInterfaceClass1::class.asClassName())
            typeSuper.addSuperinterface(
                ClassName(
                    "com.atom.compiler.apt.common",
                    "KotlinInterfaceClass1"
                )
            )
            //error com/atom/compiler/apt/common/JavaInterfaceClass0
            //typeSuper.addSuperinterface(JavaInterfaceClass0::class.asClassName())
            typeSuper.addSuperinterface(
                ClassName(
                    "com.atom.compiler.apt.common",
                    "JavaInterfaceClass1"
                )
            )
            it.addType(typeSuper.build())
        }
    }


    @Test
    fun `测试创建类,添加代码块和代码文档`() {
        createFile(PACKET, "testAddDoc") {
            val typeSuper = TypeSpec.classBuilder(
                ClassName(it.packageName, it.name)
            )

            // 代码创建 文档
            val doc: CodeBlock = CodeBlock.builder()
                .add("<p>This is a class automatically generated by API annotation processor, which is used to register the page automatically.</p>")
                .add("\n")
                .add("@date ").add(Date().toString())
                .add("\n")
                .build()

            typeSuper.addKdoc(doc)
            it.addType(typeSuper.build())
        }
    }

    @Test
    fun `测试添加注解分别为java和kotlin`() {
        createFile(PACKET, "testAddAnnotation") {
            val typeSuper = TypeSpec.classBuilder(
                ClassName(it.packageName, it.name)
            )

            val builder = AnnotationSpec.builder(
                ClassName(
                    "com.atom.compiler.apt.common",
                    "JavaAnnotation"
                )
            )
            typeSuper.annotationSpecs.add(builder.build())
            typeSuper.addAnnotation(KotlinAnnotation::class)

            it.addType(typeSuper.build())
        }
    }

    @Test
    fun `测试添加构造方法`() {
        createFile(PACKET, "testAddConstructor") {
            val typeSuper = TypeSpec.classBuilder(
                ClassName(it.packageName, it.name)
            )
            // ----------------------------
            val flux = FunSpec.constructorBuilder()
                .addParameter("greeting", String::class)
                .addStatement("this.%N = %N", "greeting", "greeting")
                .build()

            typeSuper
                .addProperty("greeting", String::class, KModifier.PRIVATE)
                .addFunction(flux)
                .build()

            it.addType(typeSuper.build())
        }
    }

    @Test
    fun `测试添加默认构造方法基于Kotlin`() {
        createFile(PACKET, "addPrimaryConstructor") {
            val typeSuper = TypeSpec.classBuilder(
                ClassName(it.packageName, it.name)
            )
            // ----------------------------
            val flux = FunSpec.constructorBuilder()
                .addParameter("greeting", String::class)
                .build()

            typeSuper.primaryConstructor(flux)
                .addProperty(
                    PropertySpec.builder("greeting", String::class)
                        .initializer("greeting")
                        .addModifiers(KModifier.PRIVATE)
                        .build()
                )
                .build()

            it.addType(typeSuper.build())
        }
    }

    @Test
    fun `测试添加类的成员`() {
        createFile(PACKET, "testAddParameters") {
            val typeSuper = TypeSpec.classBuilder(
                ClassName(it.packageName, it.name)
            )
            // ----------------------------
            val android = ParameterSpec.builder("android", String::class)
                .defaultValue("\"pie\"")
                .build()

            val welcomeOverlords = FunSpec.builder("welcomeOverlords")
                .addParameter(android)
                .addParameter("robot", String::class)
                .build()

            typeSuper.addFunction(welcomeOverlords)

            it.addType(typeSuper.build())
        }
    }
}